package com.zs.spring.reactive.loader;

import java.util.ArrayList;
import java.util.concurrent.CompletionService;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 在ExecutorService的submit方法中可以获取返回值，通过Future的get方法，但是这个Future类存在缺陷
 * Future接口调用get（）方法取得处理后的返回结果时具有阻塞性，也就是说调用Future的get方法时，任务没有执行完成
 * 则get方法要一直阻塞等到任务完成为止。
 * 这样大大的影响了系统的性能，这就是Future的最大缺点。为此，java1.5以后提供了CompletionServlice来解决这个问题。
 * CompletionService
 * 接口CompletionService的功能是异步的方式，一边生产任务，一边处理完成的任务结果，这样可以将执行的任务与处理任务隔离开来进行处理
 * 使用submit执行任务，使用塔克获取已完成的任务，并按照这些任务的完成的时间顺序来处理他们的结果。
 */
public class ParallelDataLoader extends DataLoader {
    @Override
    protected void doLoad() { // 并行计算
        ExecutorService executorService = Executors.newFixedThreadPool(3); // 创建线程池
        CompletionService completionService = new
                ExecutorCompletionService(executorService);

//        completionService.submit(new Runnable() {
//            @Override
//            public void run() {
//                loadConfigurations();
//            }
//        }, null);
//        completionService.submit(() -> loadConfigurations(), null);
        completionService.submit(super::loadConfigurations, null); // 耗时 >= 1s
        completionService.submit(super::loadUsers, null); // 耗时 >= 2s
        completionService.submit(super::loadOrders, null); // 耗时 >= 3s
        int count = 0;
        while (count < 3) { // 等待三个任务完成
            if (completionService.poll() != null) {
                count++;
            }
        }
        executorService.shutdown();
    } // 总耗时 max(1s, 2s, 3s) >= 3s

    public static void main(String[] args) {
        new ParallelDataLoader().load();
    }
}